from aiortc import RTCSessionDescription, RTCPeerConnection, RTCConfiguration, RTCIceServer

from common.log.logUtils import logUtils
from rtcCVTransform.transformFactory import AsyncVideoTransformTrack, monitorTransformTrack
from rtcCVTransform.videoTrans_Base import videoTransformBase
from signaling.socketService import socketService


class serverRtcClient:

    def __init__(self, roomId: str, videoTransfomer: videoTransformBase,clientType):
        self.answer = None
        self.pc = self.createPeerConnection()
        self.videoTransfomer = videoTransfomer
        self.bindPCEvent()
        self.roomId = roomId
        self.clientType=clientType

    def createPeerConnection(self):
        logUtils.info("create peerConnection...")
        return RTCPeerConnection(
            configuration=RTCConfiguration(
                iceServers=[
                    RTCIceServer(
                        urls="turn:iclockmaker.com:3478",
                        username="tvs",
                        credential="158246"
                    )
                ]))

    """
        bind pc event
    """

    def bindPCEvent(self):
        @self.pc.on("track")
        def on_track(input_track):
            print("触发ontrack操作......")
            self.bindMediaTrack(input_track)

            @input_track.on("ended")
            async def on_ended():
                logUtils.info("media track transport ended...")

        @self.pc.on("iceconnectionstatechange")
        async def on_iceconnectionstatechange():
            logUtils.info("ICE connection state is %s" + self.pc.iceConnectionState)
            if self.pc.iceConnectionState == "failed":
                await self.pc.close()

    '''
        input:  offer sdp
        return: answer sdp
    '''

    async def processOffer(self, roomId: str, offerDict) -> RTCSessionDescription:

        # 1.package offer to RtcSessionDescription format
        await self.setRemoteOffer(offerDict)

        await self.createAnswer()

        # 发送给客户端answer sdp
        socketService.send_to_self_with_roomId(socketService.SING_MESSAGE, roomId,
                                               {
                                                   "type": self.pc.localDescription.type,
                                                   "sdp": self.pc.localDescription.sdp
                                               }
                                               )

    # set remote offer
    async def setRemoteOffer(self, offerDict):
        logUtils.info("set remote offer start...")

        rtc_offer = self.getRTCSessionDescription(offerDict["sdp"], offerDict["type"])
        await self.pc.setRemoteDescription(rtc_offer)

        logUtils.info("set remote offer end***")

    # create answer
    async def createAnswer(self):
        logUtils.info("create answer start...")

        answer = await self.pc.createAnswer()
        print("创建的answer:"+str(answer))
        await self.pc.setLocalDescription(answer)

        logUtils.info("create answer end***")
        self.answer = self.pc.localDescription

    # bind media track to pc
    def bindMediaTrack(self, inputTrack):
        logUtils.info("bind media track start...")
        out_track = None

        input_track_kind = inputTrack.kind
        logUtils.info("input media track type:" + input_track_kind)
        if self.clientType == 1:
            if input_track_kind == "video":
                out_track = AsyncVideoTransformTrack(track=inputTrack, video_transformer=self.videoTransfomer,
                                                     roomId=self.roomId)
            elif input_track_kind == "audio":
                out_track = inputTrack
        elif self.clientType == 2:
            print("绑定监控track....")
            if input_track_kind == "video":
                out_track = monitorTransformTrack(self.roomId)
            elif input_track_kind == "audio":
                out_track = inputTrack


        self.pc.addTrack(out_track)
        logUtils.info("bind media track end***")

    # package to RtcSessionDescription format
    def getRTCSessionDescription(self, sdp, type):
        return RTCSessionDescription(sdp=sdp, type=type)
